package com.google.code.shardbatis.builder;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;

import com.google.code.shardbatis.strategy.ShardStrategy;
import com.google.code.shardbatis.util.MapperUtils;

public class ShardConfigHolder {
	
	private static final Log log = LogFactory.getLog(ShardConfigHolder.class);
	
	private static final ShardConfigHolder instance = new ShardConfigHolder();

	private Map<String, ShardStrategy> strategyRegister = new HashMap<String, ShardStrategy>();
	private Map<String, Set<String>> ignoreMap;
	private Map<String, Set<String>> parseMap;
	
	private ShardConfigHolder() {
		ignoreMap = new HashMap<String, Set<String>>();
		parseMap = new HashMap<String, Set<String>>();
	}
	
	public static ShardConfigHolder getInstance() {
		return instance;
	}

	public void register(String table, ShardStrategy strategy) {
		log.debug(table + " : " + strategy.getClass());
		this.strategyRegister.put(table.toLowerCase(), strategy);
	}

	public ShardStrategy getStrategy(String table) {
		return ((ShardStrategy) this.strategyRegister.get(table.toLowerCase()));
	}

	public synchronized void addIgnoreId(String id) {
		if (null == id || id.equals("")) { return; }
		String[] cm = MapperUtils.parseMapperId(id);
		if (this.ignoreMap.containsKey(cm[0])) {
			this.ignoreMap.get(cm[0]).add(cm[1]);
		}
		else {
			Set<String> ignoreSet = new HashSet<String>();
			ignoreSet.add(cm[1]);
			this.ignoreMap.put(cm[0], ignoreSet);
		}
	}

	public synchronized void addParseId(String id) {
		if (null == id || id.equals("")) { return; }
		String[] cm = MapperUtils.parseMapperId(id);
		if (this.parseMap.containsKey(cm[0])) {
			this.parseMap.get(cm[0]).add(cm[1]);
		}
		else {
			Set<String> parseSet = new HashSet<String>();
			parseSet.add(cm[1]);
			this.parseMap.put(cm[0], parseSet);
		}
	}

	public boolean isParseId(String id) {
		String[] cm = MapperUtils.parseMapperId(id);
		Set<String> parseSet = this.parseMap.get(cm[0]);
		return null != parseSet && (parseSet.contains("*") || parseSet.contains(cm[1]));
	}

	public boolean isIgnoreId(String id) {
		String[] cm = MapperUtils.parseMapperId(id);
		Set<String> ignoreSet = this.ignoreMap.get(cm[0]);
		return null != ignoreSet && (ignoreSet.contains("*") || ignoreSet.contains(cm[1]));
	}
}